package edu.hawaii.myisern.model;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import org.junit.AfterClass;
import org.junit.Test;

/**
 * Tests operation of the StackModel instance.
 * 
 * @author Philip Johnson
 */
public class TestDatabase {

  /** Test table name */
  private static final String dbName = "TESTTABLE";

  /**
   * Test disconnect and connect.
   */
  @Test
  public void testConnectDisconnectConnect() {
    Database db = new Database();
    db.connect();
    assertNotNull("Test db", db);
  }

  /**
   * Tests all of the public operations of the StackModel instance. (Note: not all operations are
   * tested. Left as exercise for reader.)
   * 
   * @throws Exception If problems occur during test.
   */
  @Test
  public void testDatabase() throws Exception {
    Database db = new Database();
    String sql;
    db.connect();

    // Drop table if it exists
    if (db.hasTable(dbName)) {
      sql = "DROP TABLE " + dbName;
      db.execute(sql);
    }

    // Database should not be available now.
    assertFalse("Test isTableAvail", db.hasTable(dbName));

    // Create new table
    sql = "CREATE TABLE " + dbName + " (position VARCHAR(10) PRIMARY KEY, value VARCHAR(255))";
    db.execute(sql);

    // Test is available
    assertTrue("Test isTableAvail", db.hasTable(dbName));

    // Test insert.
    sql = "INSERT INTO " + dbName + " (position, value) VALUES (?, ?)";
    String position = "100";
    String value = "Hundred";
    Integer updateCount = db.update(sql, position, value);
    Integer expectedCount = 1;
    assertEquals("Test update count", expectedCount, updateCount);

    // Test query.
    sql = "SELECT position, value FROM " + dbName;
    List<List<String>> table = db.query(sql);
    assertEquals("Test update count", 1, table.size());
    List<String> row = table.get(0);
    assertEquals("Test position", position, row.get(0));
    assertEquals("Test value", value, row.get(1));
  }

  /**
   * Test execute with a bad SQL statement.
   */
  @Test(expected = Exception.class)
  public void testBadExecute() {
    Database db = new Database();
    db.connect();
    String sql = "BAD SQL";
    db.execute(sql);
    fail("Execute should not be succesful");
  }

  /**
   * Test update with a bad SQL statement.
   */
  @Test(expected = Exception.class)
  public void testBadUpdate() {
    Database db = new Database();
    db.connect();
    String sql = "BAD SQL";
    db.update(sql);
    fail("Update should not be succesful");
  }

  /**
   * Test query with a bad SQL statement.
   */
  @Test(expected = Exception.class)
  public void testBadQuery() {
    Database db = new Database();
    db.connect();
    String sql = "BAD SQL";
    db.query(sql);
    fail("Query should not be succesful");
  }

  /**
   * Test bad driver.
   */
  @Test(expected = Exception.class)
  public void testBadConnect() {
    Database db = new Database("bad driver");
    db.connect();
    fail("2nd connect should not be succesful");
  }

  /**
   * Test bad hasTable.
   */
  @Test(expected = Exception.class)
  public void testBadHasTable() {
    Database db = new Database();
    db.hasTable("test");
    fail("isTableAvail should not be succesful");
  }

  /**
   * Drop test table.
   */
  @AfterClass
  public static void cleanUpTables() {
    Database db = new Database();
    db.connect();
    db.execute("DROP TABLE " + dbName);
  }

}
